<template>
  <section class="ft-table-transfer">
    <el-dialog
      :visible.sync="show"
      :title="title"
      :before-close="beforeClose"
      :width="width"
    >
      <el-row type="flex" justify="space-around" :gutter="20">
        <el-col :span="colSpan[0]">
          <!-- 左侧表格上部solt -->
          <slot name="left-top"></slot>
        </el-col>
        <el-col :span="colSpan[1]">
          <!-- 右侧表格上部solt -->
          <el-button type="danger" class="float-right" @click="delRight">清空</el-button>
          <slot name="right-top"></slot>
        </el-col>
      </el-row>
      <el-row
        class="table-box"
        type="flex"
        justify="space-around"
        :gutter="20"
        v-if="show"
      >
        <el-col :span="colSpan[0]">
          <!-- 左侧表格 -->
          <ft-table
            ref="left-table"
            height="400"
            has-check
            quick-check
            :data="leftData"
            :row-key="rowKey"
            :has-index="false"
            :columns="leftColumns"
            :total="selfPage.total"
            :selectable="selectable"
            :pagination="pagination"
            :reserve-selection="true"
            :page-size="selfPage.size"
            :page-num="selfPage.index"
            :defaultChecked="selfDefaultChecked"
            @current-change="currentPageChanged"
            @size-change="selfSizeChange"
            @select-all="AllSelect"
            @select="rowSelect"
          ></ft-table>
        </el-col>
        <el-col :span="colSpan[1]">
          <!-- 右侧表格 -->
          <ft-table
            ref="right-table"
            height="400"
            :row-key="rowKey"
            :data="selfRightData"
            :columns="selfRightColumns"
          >
            <template #handle="{ row }">
              <el-button
                type="text"
                icon="el-icon-delete"
                class="color-red remove-icon"
                @click="remove(row)"
              ></el-button>
            </template>
          </ft-table>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="cancel" icon="el-icon-circle-close">取 消</el-button>
        <el-button type="primary" @click="submit" icon="el-icon-circle-check"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </section>
</template>

<script>
/**
 * @author fndbs1314
 * @description 基础弹框选择数据组件, 可继承
 * @editer weilan
 * @description 重构为通用表格穿梭框
 * @editTime 2020.06.29
 * @props show 是否显示弹框
 * @props title 标题
 * @props width 弹框宽度
 * @props rowKey 表格行的key
 * @props data 备选数据
 * @props defaultChecked 默认选中数据
 * @emit select 选择数据改变
 * @emit current-change 翻页
 */
import { differenceBy } from "lodash";

export default {
  name: "table-transfer",
  props: {
    show: {
      type: Boolean,
      default: false,
    }, // 显示
    title: {
      type: String,
      default: "请选择",
    }, // 标题
    width: {
      type: String,
      default: "80%",
    }, // 宽度
    rowKey: {
      type: String,
      default: "id",
    }, // 表格行数据key，默认id
    leftColumns: {
      type: Array,
      default: () => {
        return [];
      },
    }, // 左侧表头
    leftData: {
      type: Array,
      default: () => {
        return [];
      },
    }, // 左侧数据
    rightColumns: Array, // 右侧表头，如果不传则使用左侧表头
    rightData: {
      type: Array,
      default: () => {
        return [];
      },
    }, // 右侧数据
    selectable: Function, // 是否可选
    pagination: {
      type: Boolean,
      default: true,
    }, // 是否分页
    page: Object, // 分页参数
    colSpan: {
      type: Array,
      default: () => {
        return [12, 12];
      },
    }, // 栅格占比
  },
  data() {
    return {
      selfRightData: [], // 右侧数据
    };
  },
  computed: {
    // 处理右侧表头
    selfRightColumns() {
      let prop_columns = this.rightColumns || this.leftColumns;
      const handle_item = [
        {
          label: "操作",
          slot: true,
          width: 60,
          prop: "handle",
          align: "center",
        },
      ];
      return prop_columns.concat(handle_item);
    },
    // 处理分页数据
    selfPage() {
      return {
        index: 1,
        total: 0,
        ...this.page,
      };
    },
    // 默认选中
    selfDefaultChecked() {
      return this.leftData.filter((i) =>
        this.selfRightData.some((t) => t[this.rowKey] == i[this.rowKey])
      );
    },
  },
  watch: {
    rightData: {
      handler(val) {
        this.selfRightData = [...val];
      },
      immediate: true,
    },
    show(val) {
      this.selfRightData = val ? [...this.rightData] : [];
    },
  },
  methods: {
    beforeClose() {
      this.$emit("update:show", false);
    },
    /**
     * @name 左侧行checkbox事件
     * @param {Array} data 数据
     * @param {Object} row 行数据
     * @param {Object} isCheck 是否选中
     */
    rowSelect(data, row, isCheck) {
      // 选中
      if (isCheck) {
        this.selfRightData.push(row);
      } else {
        // 取消选中
        this.selfRightData = this.selfRightData.filter(
          (i) => i[this.rowKey] !== row[this.rowKey]
        );
      }
    },
    /**
     * @name 选中全部
     */
    AllSelect(data) {
      if (data.length) {
        // 添加
        data.forEach((i) => {
          let had = this.selfRightData.find((t) => t[this.rowKey] == i[this.rowKey]);
          if (!had) {
            this.selfRightData.push(i);
          }
        });
      } else {
        // 移除
        this.selfRightData = differenceBy(this.selfRightData, this.leftData, this.rowKey);
      }
    },
    // 取消
    cancel() {
      this.beforeClose();
    },
    // 提交
    submit() {
      this.$emit("select", this.selfRightData);
    },
    /**
     * @name 翻页
     */
    currentPageChanged(val) {
      this.$emit("current-change", val);
    },
    /**
     * @name 页大小改变
     */
    selfSizeChange(val) {
      this.$emit("size-change", val);
    },
    /**
     * @name 移除已选数据
     */
    remove(row) {
      this.selfRightData = this.selfRightData.filter(
        (i) => i[this.rowKey] !== row[this.rowKey]
      );
      const left_row = this.leftData.find((i) => i[this.rowKey] == row[this.rowKey]);
      this.$refs["left-table"].toggleRowSelection(left_row, false);
    },
    // 多选移除
    delRight() {
      this.selfRightData = [];
    },
  },
};
</script>

<style lang="scss">
.ft-table-transfer {
  .table-box {
    height: 500px;
    overflow: auto;
    .ft-table {
      height: 100%;
    }
  }
  .remove-icon {
    font-size: 16px;
  }
}
</style>
>
